package com.lagou;

import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zy
 * @version 1.0
 * @date 2021/2/28 12:58
 */
@Activate(group = {"consumer"})
public class TpMonitorFilter implements Filter {

    private static Logger logger = LoggerFactory.getLogger(TpMonitorFilter.class);

    private static ConcurrentHashMap<String,Monitor> map = new ConcurrentHashMap<String, Monitor>();

    private static long upTime = 0;

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Long startTime = System.currentTimeMillis();
        Result invoke=null;
        try {
            invoke = invoker.invoke(invocation);
        }catch (Exception e){
            e.printStackTrace();
        }
        //缓存每个方法的调用情况
        String methodName = invocation.getMethodName();
        Monitor monitor = map.get(methodName);
        if(monitor==null){
            monitor= Monitor.getInstance();
        }
        map.put(methodName,monitor);

        Long ms = (System.currentTimeMillis()-startTime);
        monitor.add(ms.intValue(),methodName);//添加请求次数、耗时

        //每五秒打印一次
        if(upTime==0 || System.currentTimeMillis()-upTime>=5000) {
            upTime=System.currentTimeMillis();

            for ( Monitor monitor1 : map.values() ){
                //统计TP90
                int tp90 = monitor1.getTp(0.9F);
                //统计TP95
                int tp99 = monitor1.getTp(0.99F);

                System.out.println("__________IP:" + RpcContext.getContext().getRemoteHost()
                        + ", Service:" + invoker.getInterface().getName()
                        + ", Method:" + monitor1.getMethodName()
                        + ", requestTotolNum: " + monitor1.getNumberOfRequests() + " "
                        + ", TP90: " + tp90 + "ms "
                        + ", TP95: " + tp99 + "ms "
                );
            }

        }
        return invoke;
    }
}
